from datetime import datetime, timedelta, date
from django.db import transaction
import random
from gis.common import track_logging
from itpay.core.agency import agency_service
from itpay.core.agency.models import AgencySortScoreDetail
from itpay.core.recharge_order import const as recharge_const
from itpay.core.recharge_order import recharge_comment_service, order_service
from .const import *

_LOGGER = track_logging.getLogger(__name__)


def get_sort_agency_ids_list(agency_ids, limit=15):
    agency_score_dict = get_agency_weight_dict(agency_ids)
    result = []
    for i in range(limit):
        if not agency_score_dict:
            break
        agency_id = random_weight(agency_score_dict)
        result.append(agency_id)
        del agency_score_dict[agency_id]

    return result


def get_agency_weight_dict(agency_ids):
    agencys = agency_service.get_agencys_by_ids(agency_ids)
    agency_score_dict = dict()
    for agency in agencys:
        agency_score_dict.update({agency['id']: agency['sort_score']})

    return agency_score_dict


def random_weight(weight_data):
    total = sum(weight_data.values())
    ra = random.uniform(0, total)
    curr_sum = 0
    ret = None
    keys = weight_data.keys()
    for k in keys:
        curr_sum += weight_data[k]
        if ra <= curr_sum:
            ret = k
            break
    return ret


def get_agency_base_score(agency_id):
    agency = agency_service.get_agency_by_id(agency_id)
    if agency['created_at'] > datetime.now() - timedelta(days=7):
        return 2000
    return 1000


def get_order_comment_score(comment_id):
    comment = recharge_comment_service.get_comment_by_id(comment_id)
    if not comment['auto_comment']:
        if comment['comment_rank'] == recharge_const.OrderCommentRank.GOOD.value:
            return 2
        elif comment['comment_rank'] == recharge_const.OrderCommentRank.BAD.value:
            return -10
        else:
            return 0
    else:
        return 0


def get_user_complain_score(complain_id):
    complain = agency_service.get_complain_by_id(complain_id)

    return -100


def get_order_recharge_score(order_id):
    order = order_service.get_order(order_id)
    if order['amount'] > 500000:
        return 5
    elif order['amount'] > 100000:
        return 3
    elif order['amount'] > 10000:
        return 2
    else:
        return 1


def get_weekly_new_recharge_score():
    return 20


def is_user_weekly_new_recharge(agency_id, mch_id, user_id, this_week_monday):
    return AgencySortScoreDetail.objects.filter(agency_id=agency_id,
                                                event_type=AgencySortScoreType.NEW_USER_RECHARGE_THIS_WEEK.value,
                                                mch_id=mch_id,
                                                user_id=user_id, created_at__gt=this_week_monday).exists()


def get_this_week_monday():
    """
    获取本周周一
    :return:
    """
    today = date.today()
    monday = today - timedelta(days=today.weekday())
    return monday


SCORE_HANDLER = {
    AgencySortScoreType.USER_RECHARGE: get_order_recharge_score,
    AgencySortScoreType.NEW_USER_RECHARGE_THIS_WEEK: get_weekly_new_recharge_score,
    AgencySortScoreType.USER_COMMENT: get_order_comment_score,
    AgencySortScoreType.USER_COMPLAIN: get_user_complain_score
}


def get_score(event_type, event_id):
    return SCORE_HANDLER[event_type](event_id)


def add_agency_score_detail(agency_id, score, event_type, event_id, mch_id=None, user_id=None, remark=None):
    """
    修改代理分数
    :return:
    """
    assert isinstance(event_type, AgencySortScoreType)

    with transaction.atomic():
        agency = agency_service.get_agency_model_with_lock(agency_id)
        before_score = agency.sort_score
        if event_type == AgencySortScoreType.WEEK_INIT:
            agency.sort_score = 1000
        else:
            agency.sort_score += score
            agency.sort_score = max(500, agency.sort_score)
        agency.save()

        AgencySortScoreDetail.objects.create(agency=agency, score=score, before_score=before_score,
                                             mch_id=mch_id, user_id=user_id,
                                             event_type=event_type.value, event_id=event_id,
                                             remark=remark)


def update_agency_score(agency_id, event_type, event_id, user_id=None, mch_id=None, remark=None):
    assert isinstance(event_type, AgencySortScoreType)
    score = get_score(event_type, event_id)
    add_agency_score_detail(agency_id, score, event_type, event_id, mch_id, user_id, remark)
    if event_type == AgencySortScoreType.USER_RECHARGE:
        if not is_user_weekly_new_recharge(agency_id, mch_id, user_id, get_this_week_monday()):
            score = get_weekly_new_recharge_score()
            add_agency_score_detail(agency_id, score, AgencySortScoreType.NEW_USER_RECHARGE_THIS_WEEK, event_id, mch_id,
                                    user_id, remark)


def init_agency_weekly_score():
    page_no = 1
    page_size = 1000
    while True:
        count, agencys = agency_service.list_agency(page_no, page_size, agency_type=AgencyType.NORMAL_AGENCY)
        for agency in agencys:
            try:
                score = get_agency_base_score(agency['id'])
                add_agency_score_detail(agency['id'], score, AgencySortScoreType.WEEK_INIT,
                                        "-".join(
                                            [get_this_week_monday().strftime("%Y-%m-%d"), str(agency['id'])]))
            except Exception:
                _LOGGER.info("init_agency_weekly_score error {}".format(agency['id']), exc_info=True)
        page_no += 1
        if len(agencys) == 0:
            break
